#pragma once

#include "BasicReaderWriter.h"

namespace Rendering {

class ShaderHelper
{
public:
	/// <summary>Creates input layout.</summary>
	/// <param name="device">The direct3d device to create an input layout.</param>
	/// <param name="bytecode">The byte code for the input layout.</param>
	/// <param name="bytecodeSize">The size of the byte code.</param>
	/// <param name="layoutDesc">The layout description.</param>
	/// <param name="layoutDescNumElements">The number of elements in the layout description.</param>
	/// <param name="bytecodeSize">Thesize of the byte code.</param>
	static void CreateInputLayout(ID3D11Device* device, byte* bytecode, int bytecodeSize, 
		D3D11_INPUT_ELEMENT_DESC* layoutDesc, int layoutDescNumElements, ID3D11InputLayout** layout)
	{
		if (layoutDesc == nullptr)
		{
			// If no input layout is specified, use the following layout.
			const D3D11_INPUT_ELEMENT_DESC basicVertexLayoutDesc[] =
			{
				{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,  D3D11_INPUT_PER_VERTEX_DATA, 0 },
				{ "NORMAL",   0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
				{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT,    0, 24, D3D11_INPUT_PER_VERTEX_DATA, 0 },
			};

			IF_FAILED_THROW_HR(device->CreateInputLayout(
					basicVertexLayoutDesc,
					ARRAYSIZE(basicVertexLayoutDesc),
					bytecode,
					bytecodeSize,
					layout
					));
		}
		else
		{
			IF_FAILED_THROW_HR(device->CreateInputLayout(
					layoutDesc,
					layoutDescNumElements,
					bytecode,
					bytecodeSize,
					layout
					));
		}
	}

	/// <summary>Loads vertex shader from a file.</summary>
	/// <param name="device">The direct3d device to create an input layout.</param>
	/// <param name="filename">Name of the vertex shader file.</param>
	/// <param name="layoutDesc">The input element description.</param>
	/// <param name="layoutDescNumElements">The number of elements in the layout description.</param>
	/// <param name="shader">The created vertex shader.</param>
	/// <param name="layout">The created input layout.</param>
	static void LoadVertexShader(ID3D11Device* device, string filename,  D3D11_INPUT_ELEMENT_DESC layoutDesc[],
		int layoutDescNumElements, ID3D11VertexShader** shader,  ID3D11InputLayout** layout)
	{
		vector<byte> data = BasicReaderWriter::ReadData(filename);

		IF_FAILED_THROW_HR(device->CreateVertexShader(
				data.data(),
				data.size(),
				nullptr,
				shader           
			));

		if (layout != nullptr)
		{
			ShaderHelper::CreateInputLayout(device, 
				data.data(),
				data.size(),
				layoutDesc,
				layoutDescNumElements,
				layout
				);
		}
	}

	/// <summary>Loads pixel shader from a file.</summary>
	/// <param name="device">The direct3d device to create an input layout.</param>
	/// <param name="filename">Name of the pixel shader file.</param>
	/// <param name="shader">The created pixel shader.</param>
	static void LoadPixelShader(ID3D11Device* device, string filename, ID3D11PixelShader** shader)
	{
		vector<byte> data = BasicReaderWriter::ReadData(filename);
		device->CreatePixelShader(data.data(), data.size(),	nullptr, shader);
	}
};

}